/*
  限制输入框只能输入数字、字母、中文等规则

  使用指令：v-input

  修饰符参数说明：
    v-input.num 只能输入数字，默认不传修饰符，会自动限制只能输入数字
    v-input.intp 只能输入正整数
    v-input.num_alp 只能输入数字和字母
    v-input.num_alp_blank 只能输入数字、字母、空格
    v-input.num_alp_sym 只能输入数字和字母、英文符号、空格
    v-input.float 只能输入数字和小数点  v-input.float="2" 表示小数位数为2，默认小数位数为2，v-input.float="2"可以简写为v-input.float
    v-input.no_emoji 不能输入表情符号

*/
// 只能输入数字
function num(el) {
  el.value = el.value.replace(/\D+/g, "")
}

// 只能输入正整数
function intp(el) {
  const value = el.value.replace(/\D+/g, "") // 去掉非数字字符
  el.value = /^[1-9][0-9]*$/.test(value) ? value : value.replace(/^0+/, "") // 确保为正整数，去掉前导零
}

// 只能输入数字和字母
function num_alp(el) {
  el.value = el.value.replace(/[^A-Za-z0-9]/g, "")
}

// 只能输入数字、字母、空格
function num_alp_blank(el) {
  const regex = /[^a-zA-Z0-9 ]/g
  el.value = el.value.replace(regex, "")
}

// 只能输入数字、字母、英文符号、空格
function num_alp_sym(el) {
  const regex = /[^a-zA-Z0-9`~!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/? ]/g
  el.value = el.value.replace(regex, "")
}

// 只能输入数字和小数点，n表示小数位数
function float(el, n) {
  let value = el.value
  value = value.replace(/[^\d.]/g, "") // 能数字和小数点
  value = value.replace(/^\./g, "") // 去掉开头的点
  value = value.replace(".", "$#$").replace(/\./g, "").replace("$#$", ".") // 处理多个点的情况
  if (n && Number(n) > 0) {
    const d = new Array(Number(n)).fill("\\d").join("") // 构建正则表达式
    const reg = new RegExp(`^(\\-)*(\\d+)\\.(${d}).*$`, "ig")
    value = value.replace(reg, "$1$2.$3") // 限制小数位数
  }
  // if (value && !value.includes('.')) {
  //   value = Number(value).toString() // 去掉开头多个0
  // }
  el.value = value
}

// 限制表情：😀😂❤️🌟🎉🌍🐶☺
function no_emoji(el) {
  const regex = /[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F1E6}-\u{1F1FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{1F900}-\u{1F9FF}\u{263A}]+/gu
  el.value = el.value.replace(regex, "")
}

// 这里扩展限制的类型
const map = { num, intp, num_alp, num_alp_blank, num_alp_sym, float, no_emoji }

export default {
  bind(el, binding, vnode) {
    el = el.querySelector(".el-input__inner") || el.querySelector(".el-textarea__inner") || el.querySelector(".van-field__control") || el
    let lock = false // 标记是否需要锁定输入框
    let isHandling = false // 标记是否正在处理
    let lastValue = null
    // input事件处理函数
    const handler = () => {
      if (lock) return // 如果当前为锁定状态，则不进行处理
      if (isHandling) return // 如果已经在处理中，则不进行处理
      if (el.value === lastValue) return // 输入内容没有变化，则不进行处理
      isHandling = true // 设置标记为处理中
      const modifiers = Object.keys(binding.modifiers)
      const newModifier = modifiers[0] || "num"
      map[newModifier](el, binding.value || 2)
      lastValue = el.value // 记录当前输入框的值
      Promise.resolve().then(() => {
        // 异步处理，场景：火狐浏览器中，需要在最后派发input事件
        el.dispatchEvent(new Event("input"))
      })
      isHandling = false // 处理完毕后设置标记为非处理状态
    }
    el.addEventListener("input", handler)
    // compositionstart和compositionend事件解决的bug场景：限制只能输入数字的输入框，先输入数字，再切换为中文输入法，输入字母时，会将原来的数字删掉
    el.addEventListener("compositionstart", () => {
      lock = true
    })
    el.addEventListener("compositionend", () => {
      lock = false
      el.dispatchEvent(new Event("input"))
    })
    // 当指令与元素解绑时，移除事件监听器
    vnode.context.$once("hook:destroyed", () => {
      el.removeEventListener("input", handler)
    })
  },
}
